package autohotkeyide.hightlighter;

import autohotkeyide.IDETextField;
import autohotkeyide.autocompletion.AutoCompletionManager;
import autohotkeyide.autocompletion.CommandCompletion;
import autohotkeyide.autocompletion.VariableCompletion;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Timer;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;

/**
 * @author sad
 */
public class Highlighter {

    private SimpleAttributeSet variableAttributeSet;
    private SimpleAttributeSet functionAttributeSet;
    private SimpleAttributeSet defaultAttributeSet;

    private enum LEXEMTYPE {

        FUNCTION, VARIABLE, TEXT
    };
    private IDETextField field;
    private AutoCompletionManager autocompletionManager;
    private HashMap<String, LEXEMTYPE> systemFunctionsList = new HashMap<String, LEXEMTYPE>();
    private Timer hightlightTimer;
    public Highlighter(IDETextField field, AutoCompletionManager autocompletionManager) {
        this.field = field;
        this.autocompletionManager = autocompletionManager;
        loadSystemFunctionsList();
        createAttributesSet();
        field.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                onDocumentChanged();
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                onDocumentChanged();
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
            }
        });
    }

    public void onDocumentChanged() {
        if(hightlightTimer==null){
            hightlightTimer=new Timer(100, new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    paintAll();
                }
            });
            hightlightTimer.setRepeats(false);
        }
        hightlightTimer.restart();
        
    }

    private void loadSystemFunctionsList() {
        systemFunctionsList.clear();
        for (CommandCompletion command : autocompletionManager.getSystemFunctionsList()) {
            systemFunctionsList.put(command.getInputText(), LEXEMTYPE.FUNCTION);
        }

        for (VariableCompletion variable : autocompletionManager.getSystemVariablesList()) {
            systemFunctionsList.put(variable.getInputText(), LEXEMTYPE.VARIABLE);
        }
    }

    private void createAttributesSet() {
        functionAttributeSet = new SimpleAttributeSet();
        StyleConstants.setForeground(functionAttributeSet, Color.BLUE);
        variableAttributeSet = new SimpleAttributeSet();
        StyleConstants.setForeground(variableAttributeSet, new Color(0,100,0));
        defaultAttributeSet = new SimpleAttributeSet();
    }

    public void paintAll() {
        StyledDocument document = ((StyledDocument) field.getDocument());
        String text=null;
        try {
            text = document.getText(0, document.getLength());
        } catch (BadLocationException ex) {
            Logger.getLogger(Highlighter.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        WordParser parser = new WordParser();
        parser.setText(text);
        String word;
        document.setCharacterAttributes(0, text.length(), defaultAttributeSet, true);
        while ((word = parser.getNextWord()) != null) {
            if (systemFunctionsList.containsKey(word)) {
                LEXEMTYPE type = systemFunctionsList.get(word);
                AttributeSet attribute;
                if (type == LEXEMTYPE.FUNCTION) {
                    attribute = functionAttributeSet;
                } else {
                    attribute = variableAttributeSet;
                }

                document.setCharacterAttributes(parser.getLastWordPosition(), word.length(), attribute, true);
            }
        }
    }
}
